package com.common.physics
{
	import com.common.utils.Math2;
	
	public class CollisionDetection
	{
		public function CollisionDetection()
		{
		}

		public static function pointCircleIntersection(radius:Number, circleCentreX:Number, circleCentreY:Number, pointX:Number, pointY:Number) : Boolean{
			if(radius >= Math2.getDistance(circleCentreX, circleCentreY, pointX, pointY))
				return true;
			else
				return false;
		}
		
		public static function circleRectangleIntersection(radius:Number, circleCentreX:Number, circleCentreY:Number, rectLeft:Number, rectTop:Number, rectRight:Number, rectBottom:Number) : Boolean{
			var rectWidth:Number = rectRight - rectLeft;
			var rectHeight:Number = rectBottom - rectTop;
			var rectCentreX:Number = rectRight - rectWidth/2.0;
			var rectCentreY:Number = rectBottom - rectHeight/2.0;
			var rectDiagonal:Number = Math.sqrt(rectWidth/2.0 * rectWidth/2.0 + rectHeight/2.0 * rectHeight/2.0);
			var distanceBetweenCentres:Number = Math2.getDistance(circleCentreX, circleCentreY, rectCentreX, rectCentreY);
			if(distanceBetweenCentres > rectDiagonal + radius)
				return false;
//			var angleOfElevation_Degrees:Number = Math2.getAngleOfElevationDegree(rectCentreX, rectCentreY, circleCentreX, circleCentreY);
			var angleOfElevation_Degrees:Number = Math2.convertTo360DegreeAngle(Math2.getAngleOfElevationDegree(rectCentreX, rectCentreY, circleCentreX, circleCentreY));
//			trace("Angle",angleOfElevation_Degrees, "cirCenX", circleCentreX, "cirCenY", circleCentreY);
			if(((angleOfElevation_Degrees == 0 || angleOfElevation_Degrees == 180) && (distanceBetweenCentres > rectWidth/2.0 + radius)) ||
				((angleOfElevation_Degrees == 90 || angleOfElevation_Degrees == 270) && (distanceBetweenCentres > rectHeight/2.0 + radius))) {
				return false;
			}
			if((angleOfElevation_Degrees == 45 || angleOfElevation_Degrees == 135 || angleOfElevation_Degrees == 225 || angleOfElevation_Degrees == 315)
				&& distanceBetweenCentres < rectDiagonal + radius)
				return true; 
			var oppSideLength:Number;
			var rectBoundaryPointX:Number;
			var rectBoundaryPointY:Number;
			var tanOfAngleOfElevation:Number = Math.tan(Math2.toRad(angleOfElevation_Degrees));
			var tanOfAngleOfElevation_OffVertical:Number;
			
			//Potential point of intersection lies on rectangle's right side
			if(angleOfElevation_Degrees < 45){
				oppSideLength = rectWidth/2.0 * Math.abs(tanOfAngleOfElevation);
				rectBoundaryPointX = rectRight;
				rectBoundaryPointY = rectBottom - rectHeight/2.0 + oppSideLength;
//				trace("tan", tanOfAngleOfElevation, "oppSid", oppSideLength, "rectBX", rectBoundaryPointX, "rectBY", rectBoundaryPointY);
			}
			if(angleOfElevation_Degrees > 315){
//			if(angleOfElevation_Degrees > -45){
				oppSideLength = rectWidth/2.0 * Math.abs(tanOfAngleOfElevation);
				rectBoundaryPointX = rectRight;
				rectBoundaryPointY = rectBottom - rectHeight/2.0 - oppSideLength;
				//trace("3");
			}
			//Potential point of intersection lies on rectangle's left side
			if(angleOfElevation_Degrees > 135 && angleOfElevation_Degrees < 180){
				oppSideLength = rectWidth/2.0 * Math.abs(tanOfAngleOfElevation);
				rectBoundaryPointX = rectLeft;
				rectBoundaryPointY = rectBottom - rectHeight/2.0 + oppSideLength;
//				trace("tan", Math.abs(tanOfAngleOfElevation), "oppSid", oppSideLength, "rectBX", rectBoundaryPointX, "rectBY", rectBoundaryPointY);
				//trace("4");
			}
			if(angleOfElevation_Degrees > 180 && angleOfElevation_Degrees < 225){
				oppSideLength = rectWidth/2.0 * Math.abs(tanOfAngleOfElevation);
				rectBoundaryPointX = rectLeft;
				rectBoundaryPointY = rectBottom - rectHeight/2.0 - oppSideLength;
				//trace("5");
			}
			
			//Potential point of intersection lies on rectangle's bottom side
			if(angleOfElevation_Degrees > 45 && angleOfElevation_Degrees < 90){
				tanOfAngleOfElevation_OffVertical = Math.tan(Math2.toRad(90 - angleOfElevation_Degrees));
				oppSideLength = rectHeight/2.0 * Math.abs(tanOfAngleOfElevation_OffVertical);
				rectBoundaryPointX = rectRight - rectWidth/2.0 + oppSideLength;
				rectBoundaryPointY = rectBottom;
				//trace("6");
			}
			if(angleOfElevation_Degrees > 90 && angleOfElevation_Degrees < 135){
				tanOfAngleOfElevation_OffVertical = Math.tan(Math2.toRad(angleOfElevation_Degrees - 90));
				oppSideLength = rectHeight/2.0 * Math.abs(tanOfAngleOfElevation_OffVertical);
				rectBoundaryPointX = rectRight - rectWidth/2.0 - oppSideLength;
				rectBoundaryPointY = rectBottom;
				//trace("7");
			}
			//Potential point of intersection lies on rectangle's top side
			if(angleOfElevation_Degrees > 225 && angleOfElevation_Degrees < 270){
				tanOfAngleOfElevation_OffVertical = Math.tan(Math2.toRad(270 - angleOfElevation_Degrees));
				oppSideLength = rectHeight/2.0 * Math.abs(tanOfAngleOfElevation_OffVertical);
				rectBoundaryPointX = rectRight - rectWidth/2.0 - oppSideLength;
				rectBoundaryPointY = rectTop;
				//trace("8");
			}
			if(angleOfElevation_Degrees > 270 && angleOfElevation_Degrees < 315){
				tanOfAngleOfElevation_OffVertical = Math.tan(Math2.toRad(angleOfElevation_Degrees - 270));
				oppSideLength = rectHeight/2.0 * Math.abs(tanOfAngleOfElevation_OffVertical);
				rectBoundaryPointX = rectRight - rectWidth/2.0 + oppSideLength;
				rectBoundaryPointY = rectTop;
//				trace("tan", Math.abs(tanOfAngleOfElevation_OffVertical), "oppSid", oppSideLength, "rectBX", rectBoundaryPointX, "rectBY", rectBoundaryPointY);				
				//trace("9");
			}
//			trace(angleOfElevation_Degrees);
			if(distanceBetweenCentres + radius < Math2.getDistance(rectCentreX, rectCentreY, rectBoundaryPointX, rectBoundaryPointY))
				return true;
//			trace(radius, circleCentreX, circleCentreY, rectBoundaryPointX, rectBoundaryPointY);
			return pointCircleIntersection(radius, circleCentreX, circleCentreY, rectBoundaryPointX, rectBoundaryPointY);
		}
		
		public static function pointRectangleIntersection(pointX:Number, pointY:Number, rectLeft:Number, rectTop:Number, rectRight:Number, rectBottom:Number) : Boolean{
			return (pointX <= rectRight && pointX >= rectLeft && pointY <= rectBottom && pointY >= rectTop);
		}

	}
}